#ifndef LOADXML_H_
#define LOADXML_H_

#include "tinyxml.h"
#include "Materiais.h"
#include "Texturas.h"
#include "Luzes.h"
#include "Iluminacao.h"
#include "Cena.h"
#include "Transformacoes.h"
#include "View.h"
#include "Translacao.h"
#include "Rotacao.h"
#include "Escalamento.h"
#include "Retangulo.h"
#include "Triangulo.h"
#include "Cilindro.h"
#include "Esfera.h"
#include "Torus.h"
#include "Componente.h"

#include <GL/glui.h>
#include <iostream>
#include <map>

using namespace std;

class LoadXML {

private:

	TiXmlDocument doc;
	TiXmlElement* no;
	TiXmlElement* textElemento;
	TiXmlElement* matElemento;
	TiXmlElement* transElemento;
	TiXmlElement* luzElemento;
	TiXmlElement* ilElemento;
	TiXmlElement* vistElemento;

	map<string, Texturas*> texturas;
	map<string, Materiais*> materiais;
	map<string, Luzes*> luzes;
	map<string, View*> vistas;
	map<string, Transformacoes*> transformacoes;
	map<string, Primitiva*> primitivas;
	map<string, Componente*> componentes;
	Iluminacao *iluminacao;
	Cena *ceninha;

public:
	
	void loadXML(string fileName);
	bool loadCena();
	bool loadMateriais();
	bool loadTexturas();
	bool loadTransformacoes();
	bool loadLuzes();
	bool loadIluminacao();
	bool loadVistas();
	bool loadPrimitivas();
	bool loadComponentes();

	void addTextura(string id, Texturas *t);
	void addMaterial(string id, Materiais *m);
	void addVista(string id, View *v);
	void defineIluminacao(Iluminacao *i);
	void addLuz(string id, Luzes *l);
	void addTransformacao(string id, Transformacoes *trans);
	void addComponente(string id, Componente *comp);
	void addRectangulo(string id, Rectangulo *r);
	void addTriangulo(string id, Triangulo *t);
	void addCilindro(string id, Cilindro *c);
	void addEsfera(string id, Esfera *e);
	void addTorus(string id, Torus *to);
	void aplicaLuzes();
	void setCena(Cena *c) {
		this->ceninha = c;
	}
	Componente* getComponente(string id) {
		map<string,Componente*>::iterator it = componentes.find(id);

        if(it==componentes.end())
                return NULL;
        else
                return it->second;

	}

	int numArg(TiXmlElement *arg){
		int i = 0;
		for(TiXmlAttribute *coiso(arg->FirstAttribute()); coiso != NULL; coiso = coiso->Next()) {
			i++;
		}
		return i;
	}

	Texturas* encontra_T(string id) {

		map<string,Texturas*>::iterator it = texturas.begin();
		for(; it != texturas.end(); it++){
			if(it->first == id)
				return it->second;
		}
		return NULL;
	}

	Materiais* encontra_M(string id) {
		int i = 0;
		map<string,Materiais*>::iterator it = materiais.begin();
		for(; it != materiais.end(); it++){
			if(it->first == id) {
				return it->second;
			}
			i++;
		}
		return NULL;
	}

	Transformacoes* encontra_Tr(string id) {
		map<string,Transformacoes*>::iterator it = transformacoes.begin();
		for(; it != transformacoes.end(); it++){
			if(it->first == id)
				return it->second;
		}

		return NULL;
	}

	Primitiva * encontra_P(string id) {
		map<string, Primitiva*>::iterator it = primitivas.begin();
		for(; it != primitivas.end(); it++) {
			if(it->first == id) {
				return it->second;
			}
		}
		return NULL;
	}

	Componente * encontra_C(string id) {
		map<string, Componente*>::iterator it = componentes.begin();
		for(; it != componentes.end(); it++) {
			if(it->first == id) {
				return it->second;
			}
		}
		return NULL;
	}


	
	void leMapTexturas() {
		map<string,Texturas*>::iterator it = texturas.begin();
		for(; it != texturas.end(); it++) {
			cout << "id: " << it->first << " textura: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}

	void leMapMateriais() {
		map<string,Materiais*>::iterator it = materiais.begin();
		for(; it != materiais.end(); it++) {
			cout << "id: " << it->first << " material: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}

	void leMapIluminacao() {
		cout << "Doublesided: " << this->iluminacao->getDoublesided() << endl;
		cout << "Local: " << this->iluminacao->getLocal() << endl;
		cout << "Ambiente: ";
		for(int i = 0; i != 4 ;i++) {
			cout << this->iluminacao->getAmbiente()[i] << " ";
		}
		cout << endl;

		cout << "Background: ";
		for(int j = 0; j != 4 ;j++) {
			cout << this->iluminacao->getBackground()[j] << " ";
		}
		cout << endl;
		cout << "FIMM!!" << endl;
	}

	void leMapVistas() {
		map<string,View*>::iterator it = vistas.begin();
		for(; it != vistas.end(); it++) {
			cout << "id: " << it->first << " vista: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}

	void leMapLuzes() {
		map<string,Luzes*>::iterator it = luzes.begin();
		for(; it != luzes.end(); it++) {
			cout << "IDDDDDDDDDDDD: " << it->first << " Luz: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}

	void leMapPrimitivas() {
		map<string,Primitiva*>::iterator it = primitivas.begin();
		for(; it != primitivas.end(); it++) {
			cout << "IDDDDDDDDDDDD: " << it->first << " prim: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}
	
	void leMapTransformacoes() {
		map<string,Transformacoes*>::iterator it = transformacoes.begin();
		for(; it != transformacoes.end(); it++) {
			cout << "IDDDDDDDDDDDD: " << it->first << " prim: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}

	void leMapComponentes() {
		map<string,Componente*>::iterator it = componentes.begin();
		for(; it != componentes.end(); it++) {
			cout << "IDDDDDDDDDDDD: " << it->first << " prim: " << it->second << endl;
		}
		cout << "FIMM!!" << endl;
	}

	void cicloComponentes() {
		map<string,Componente*>::iterator it = componentes.begin();
		/*for(; it != componentes.end(); it++) {
			cout << "tamanhi : " << (*it).first << endl;
			cout << "tamanho_vector_materiais: " << (*it).second->getMateriais().size() << endl;
			cout << "Estou aqui_4" << endl;
			it->second->aplica();
			cout << "Estou aqui_5" << endl;
		}*/
		glPushMatrix();
		Componente *c = getComponente(this->getCeninha()->getNome());
		c->aplica();
		glPopMatrix();
	}

	Cena *getCeninha() {
		return this->ceninha;
	}

	void cicloLuzes() {
		map<string,Luzes*>::iterator it = luzes.begin();
		for(; it != luzes.end(); it++) {
			it->second->aplica();
		}
	}
};
#endif